/**
 * LICENCIA LGPL:
 * 
 * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla
 * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como 
 * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de 
 * la Licencia, o (a su elección) cualquier versión posterior.
 * 
 * Esta librería se distribuye con la esperanza de que sea útil, pero SIN 
 * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o 
 * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public 
 * License (LGPL) para más detalles
 * 
 * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) 
 * junto con esta librería; si no es así, escriba a la Free Software Foundation 
 * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte
 * <http://www.gnu.org/licenses/>.
 *
 * Copyright 2011 Agencia de Tecnología y Certificación Electrónica
 */
package es.accv.arangi.base.device;

import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

import org.apache.log4j.Logger;

import es.accv.arangi.base.exception.device.OpeningDeviceException;
import es.accv.arangi.base.exception.device.WindowsNotFoundException;

/**
 * SOLO FUNCIONA CON VERSIONES DE JAVA A PARTIR DE LA 1.6.<BR><BR>
 * 
 * Clase para tratar el almacén de certificados de autoridades de certificación
 * de Windows. Aunque se han dejado todos los métodos de cualquier manager de
 * keystore, en este almacén no tiene mucha lógica generar pares de claves o
 * importar claves privadas en general<br><br>
 * 
 * Ejemplo de uso:<br><br>
 * 
 * <code>
 *  IDocument document = new FileDocument(new File ("/documento.txt"));<br>
 * 	CAWindowsKeyStoreManager manager = new CAWindowsKeyStoreManager ();<br>
 * 	String aliases = manager.getAliasNamesList();<br>
 * 	for (int i=0;i<aliases.length;i++) {<br>
 *  &nbsp;&nbsp;System.out.println ("Certificate: " + manager.getCertificate(aliases[i]));<br>
 * 	&nbsp;&nbsp;System.out.println ("Firma: " + manager.signDocument(document, aliases[i])); // Firma con la clave privada del alias<br>
 * 	}<br>
 * </code><br>
 * 
 * Cada vez que se trata de insertar un certificado Windows mostrará una ventana
 * de aviso.
 * 
 * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a>
 */
public class CAWindowsKeyStoreManager extends AbstractBrowserKeyStoreManager {

	/*
	 * Logger de la clase
	 */
	Logger logger = Logger.getLogger(CAWindowsKeyStoreManager.class);
	
	//-- Constructores
	
	/**
	 * Constructor: inicializa el keystore de certificados de CA de Windows.
	 * 
	 * @throws OpeningDeviceException Error abriendo el keystore personal de Windows
	 * @throws WindowsNotFoundException No existe el almacén de claves de Windows debido
	 * 	a que la ejecución se produce en un sistema operativo diferente
	 */
	public CAWindowsKeyStoreManager () throws OpeningDeviceException, WindowsNotFoundException {
		
		if (!System.getProperty("os.name").contains("indows")) {
			logger.info("[AppleSafariKeyStoreManager]:: El sistema operativo no es Mac OS X sino " + System.getProperty("os.name"));
			throw new WindowsNotFoundException("El sistema operativo no es Windows sino " + System.getProperty("os.name"));
		}

		this.pin = "";
		this.ksType = STORE_TYPE_PERSONAL_WINDOWS;
		
		try {
			this.ks = KeyStore.getInstance("Windows-ROOT");
			ks.load(null);
		} catch (KeyStoreException e) {
			logger.info("[CAWindowsKeyStoreManager]::No se puede obtener una instancia del keystore de certificados de CA de Windows", e);
			throw new OpeningDeviceException ("No se puede obtener una instancia del keystore de certificados de CA de Windows", e);
		} catch (NoSuchAlgorithmException e) {
			logger.info("[CAWindowsKeyStoreManager]::No existe el algoritmo que comprueba la integridad del keystore de certificados de CA de Windows", e);
			throw new OpeningDeviceException ("No existe el algoritmo que comprueba la integridad del keystore de certificados de CA de Windows", e);
		} catch (CertificateException e1) {
			logger.info("[CAWindowsKeyStoreManager]::Alguno de los certificados del dispositivo no puede ser cargado", e1);
			throw new OpeningDeviceException ("Alguno de los certificados del dispositivo no puede ser cargado", e1);
		} catch (IOException e1) {
			logger.info("[CAWindowsKeyStoreManager]::Error de entrada/salida cargando el keystore de certificados de CA de Windows", e1);
			throw new OpeningDeviceException ("Error de entrada/salida cargando el keystore de certificados de CA de Windows", e1);
		}
	}
	
	//-- Métodos públicos
	
	/**
	 * Cerrar el keystore y eliminar el provider de SUN de la lista de proveedores
	 */
	public void close() {
		logger.debug ("Cerrando Keystore...");

		ks = null;

		logger.debug("Cerrado Keystore...OK");
	}

	@Override
	public void initialize() {
		try {
			this.ks = KeyStore.getInstance("Windows-ROOT");
			ks.load(null);
		} catch (KeyStoreException e) {
			logger.error("[CAWindowsKeyStoreManager.initialize]::", e);
		} catch (NoSuchAlgorithmException e) {
			logger.error("[CAWindowsKeyStoreManager.initialize]:: Error al reinicializar el KeyStore", e);
		} catch (CertificateException e) {
			logger.error("[CAWindowsKeyStoreManager.initialize]:: Error al reinicializar el KeyStore", e);
		} catch (IOException e) {
			logger.error("[CAWindowsKeyStoreManager.initialize]:: Error al reinicializar el KeyStore", e);
		}
		
	}

	/* (non-Javadoc)
	 * @see es.accv.arangi.base.device.DeviceManager#isAliasFree(java.lang.String)
	 */
	public boolean isAliasFree(String alias){
		
		logger.debug ("[CAWindowsKeyStoreManager.isAliasFree]::Entrada::" + alias);
		
		boolean isFree = false;
		try {
			isFree = !ks.containsAlias(alias);
		} catch (KeyStoreException e) {
			logger.info("[CAWindowsKeyStoreManager.isAliasFree]::Error comprobando si existe el alias '" + alias + "'", e);
		}
		return isFree;
	}
	

}